package main

import (
	"bytes"
	"encoding/base64"
	"fmt"
	"image"
	"image/color"
	"image/png"
	"io"
	"io/ioutil"
	"os"
)

func main() {
	imgBase64, err := ioutil.ReadFile("./store/pic.txt")
	if err != nil {
		fmt.Println("读取BASE64文件失败：", err)
		return
	}
	msg := "s1:{sss:xqx2}"
	key := "1"
	//fmt.Println(imgBase64, msg, key)

	//setBit(0, 0, 1)
	readImg(string(imgBase64), msg, key)
}

func readImg(base64Img, msg, key string) {
	dist, err := base64.StdEncoding.DecodeString(base64Img)
	if err != nil {
		fmt.Println("解码64图片出错:", err)
		return
	}
	f, err := os.OpenFile("./store/pic111.png", os.O_RDWR|os.O_CREATE, os.ModePerm)
	if err != nil {
		fmt.Println("新建文件失败：", err)
		return
	}
	defer f.Close()
	f.Write(dist)

	msgLen := len(msg)
	fmt.Println(msgLen)
	x1 := GetBitsFromNumber(msgLen)
	x2 := GetBitsFromMessage(msg)
	fmt.Println(x1)
	fmt.Println(x2)
	x := append(x1, x2...)
	fmt.Println(x)
	fmt.Println(len(x))

	b := bytes.NewBuffer(dist)
	imageHandler(b, x)

	fmt.Println("----------decode")
	fd, err := os.OpenFile("./store/new_pic.png", os.O_RDWR|os.O_CREATE, os.ModePerm)
	if err != nil {
		fmt.Println("新建文件失败：", err)
		return
	}
	msgLen, y := getImageBit(fd)
	fmt.Println(msgLen, y)
	fmt.Println(len(y))
	ct := []rune{}
	for i := 0; i < msgLen; i++ {
		ct = append(ct, rune(getNumberFromBits(y[i*16:i*16+16])))
	}
	fmt.Println(ct)
	fmt.Println(string(ct))
}

func imageHandler(reader io.Reader, bits []uint8) {
	img, err := png.Decode(reader)
	if err != nil {
		fmt.Println("解码Img失败：", err)
		return
	}
	rect := img.Bounds()
	dx := rect.Max.X
	dy := rect.Max.Y
	rgba := image.NewRGBA(image.Rect(0, 0, dx, dy))
	loc := len(bits)
	index := 0
	i := 0
	for x := 0; x < dx; x++ {
		for y := 0; y < dy; y++ {
			c := img.At(x, y)
			r, g, b, a := c.RGBA()
			i++
			newColor := color.NRGBA{}
			if index < loc {
				newColor = color.NRGBA{uint8(r), uint8(g), bits[index], uint8(a)}
				index++
			} else {
				newColor = color.NRGBA{uint8(r), uint8(g), uint8(b), uint8(a)}
			}
			//fmt.Println(newColor)
			rgba.Set(x, y, newColor)
			//fmt.Println(img.At(x, y))
		}
	}
	fmt.Println(rect)
	fmt.Println(i)
	f, err := os.OpenFile("./store/new_pic.png", os.O_RDWR|os.O_CREATE, os.ModePerm)
	if err != nil {
		fmt.Println("新建文件失败：", err)
		return
	}
	err = png.Encode(f, rgba)
	if err != nil {
		fmt.Println("存储新的图像失败")
	}
}

func getImageBit(reader io.Reader) (msgLens int, bits []uint8) {
	img, err := png.Decode(reader)
	if err != nil {
		fmt.Println("解码Img失败：", err)
		return
	}
	rect := img.Bounds()
	dx := rect.Max.X
	dy := rect.Max.Y
	var (
		lenBits, msgBits []uint8
		msgLen           int
	)

	index := 0
	for x := 0; x < dx; x++ {
		for y := 0; y < dy; y++ {
			if index < 16 {
				c := img.At(x, y)
				_, _, lenBit, _ := c.RGBA()
				lenBits = append(lenBits, uint8(lenBit))
				index++
				continue
			}
			if index == 16 {
				msgLen = getNumberFromBits(lenBits)
				fmt.Println(msgLen)
			}
			if index >= 16 && index < msgLen*16+16 {
				c := img.At(x, y)
				_, _, msg, _ := c.RGBA()
				msgBits = append(msgBits, uint8(msg))
				index++
			}
		}
	}
	bits = msgBits
	msgLens = msgLen
	return
}

func GetBitsFromMessage(msg string) []uint8 {
	var msgBit []uint8
	for _, v := range msg {
		msgBit = append(msgBit, GetBitsFromNumber(int(v))...)
	}
	return msgBit
}

func GetBitsFromNumber(number int) []uint8 {
	var bits = []uint8{}
	for i := 0; i < 16; i++ {
		bits = append(bits, getBit(number, i))
	}
	return bits
}

func getBit(number, location int) uint8 {
	x := (number >> location) & 1
	return uint8(x)
}

func setBit(number, pos, bit int) int {
	x := number & ^(1<<pos) | (bit << pos)
	return x
}

func getNumberFromBits(bits []uint8) int {
	var number, pos int
	for pos < 16 {
		number = setBit(number, pos, int(bits[pos]))
		pos++
	}
	return number
}
